package util;


import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;


/**
 * RSA 工具类。提供加密，解密，生成密钥对等方法。
 * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
 * 
 */
public class RSACipherUtil {
  //  private static Logger logger = LoggerFactory.getLogger(RSACipherUtil.class);

    public static RSAPublicKey generateRSAPublicKey(byte[] modulus,
                                                    byte[] publicExponent) {
        KeyFactory keyFac = null;
        try {
            keyFac = KeyFactory.getInstance("RSA");
            RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(
                    modulus), new BigInteger(publicExponent));
            return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);

        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public static byte[] encrypt(PublicKey pk, byte[] data) {
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding" ); //RSA_PKCS1_PADDING

            cipher.init(Cipher.ENCRYPT_MODE, pk);

            int blockSize = 117;//cipher.getBlockSize();

            int outputSize = cipher.getOutputSize(data.length);
            int leavedSize = data.length % blockSize;
            int blocksSize = leavedSize != 0 ? data.length / blockSize + 1
                    : data.length / blockSize;
            byte[] raw = new byte[outputSize * blocksSize];
            int i = 0;

            while (data.length - i * blockSize > 0)
            {
                if (data.length - i * blockSize > blockSize)
                    cipher.doFinal(data, i * blockSize, blockSize, raw, i
                            * outputSize);
                else
                    cipher.doFinal(data, i * blockSize, data.length - i
                            * blockSize, raw, i * outputSize);

                i++;
            }
            return raw;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}
